import * as step from '@flow-step/step-toolkit'
import * as sinon from 'sinon'
import {expect} from 'chai'
import { describe, before, after, it } from 'mocha'
import { IParams } from '../src/params'
const proxyquire = require('proxyquire')

type KubernetesCertificate = {
    type: string,
    kubeConfig: string,
    miranaProxy: string
    jwtToken: string
}

describe('Kubernetes Certificate', () => {
    let sandbox: sinon.SinonSandbox
    let getKubernetesCertificateStub: any
    let writeFileSyncStub: sinon.SinonStub
    let existsSyncStub: sinon.SinonStub
    let mkdirSyncStub: sinon.SinonStub
    let homedirStub: sinon.SinonStub
    let execute: Function

    beforeEach(() => {
        sandbox = sinon.createSandbox()
        writeFileSyncStub = sandbox.stub()
        existsSyncStub = sandbox.stub()
        mkdirSyncStub = sandbox.stub()
        homedirStub = sandbox.stub()

        getKubernetesCertificateStub = sandbox.stub(step.certificate, 'getKubernetesCertificate')
        execute = proxyquire('../src/execute', {
          fs: {
            writeFileSync: writeFileSyncStub,
            existsSync: existsSyncStub,
            mkdirSync: mkdirSyncStub
          },
          os: {
            homedir: homedirStub
          }
        }).execute
        homedirStub.returns('/root')
    })

    afterEach(() => {
        sandbox.restore()
    })

    it('should failed to save file if exists', async () => {
        const mockCertificate: KubernetesCertificate = {
            type: 'custom',
            kubeConfig: 'mockKubeConfig',
            miranaProxy: '',
            jwtToken: ''
        }
        getKubernetesCertificateStub.resolves(mockCertificate)
        existsSyncStub.returns(true)
        
        try {
          await execute({
            kubernetesCluster: 'mockKubernetesConnectionId',
            jobToken: 'mockFlowJobToken'
          } as IParams)
        } catch (error) {
          expect((error as Error).message).to.equal('/root/.kube/config already exists, please remove it first');
        }
    })

    it('should failed to save custom kubeconfig if not exists', async () => {
      const mockCertificate: KubernetesCertificate = {
          type: 'custom',
          kubeConfig: '',
          miranaProxy: '',
          jwtToken: ''
      }
      getKubernetesCertificateStub.resolves(mockCertificate)
      existsSyncStub.returns(false)
      
      try {
        await execute({
          kubernetesCluster: 'mockKubernetesConnectionId',
          jobToken: 'mockFlowJobToken'
        } as IParams)
      } catch (error) {
        expect((error as Error).message).to.equal('未获取到合法的Kubernetes证书文件，请检查流水线配置后再试');
      }
    })
    
    it('should save custom kubeconfig to default file path', async () => {
      const mockCertificate: KubernetesCertificate = {
        type: 'custom',
        kubeConfig: 'mockKubeConfig',
        miranaProxy: '',
        jwtToken: ''
      }
      getKubernetesCertificateStub.resolves(mockCertificate)
      existsSyncStub.returns(false)
      
      await execute({
        kubernetesCluster: 'mockKubernetesConnectionId',
        jobToken: 'mockFlowJobToken'
      } as IParams)
      sinon.assert.calledWith(writeFileSyncStub, '/root/.kube/config', 'mockKubeConfig')
    })

    it('should save custom kubeconfig to custom file path', async () => {
      const mockCertificate: KubernetesCertificate = {
        type: 'custom',
        kubeConfig: 'mockKubeConfig',
        miranaProxy: '',
        jwtToken: ''
      }
      getKubernetesCertificateStub.resolves(mockCertificate)
      existsSyncStub.returns(false)
      
      await execute({
        kubeConfigPath: '~/.kube/custom-kube-config',
        kubernetesCluster: 'mockKubernetesConnectionId',
        jobToken: 'mockFlowJobToken'
      } as IParams)

      sinon.assert.calledWith(writeFileSyncStub, '/root/.kube/custom-kube-config', 'mockKubeConfig')
    })

    it('should save ack kubeconfig to file', async () => {
      const mockCertificate: KubernetesCertificate = {
        type: 'ack',
        kubeConfig: '',
        miranaProxy: 'https://rdc.aliyuncs.com/mirana',
        jwtToken: 'somejwttoken'
      }
      getKubernetesCertificateStub.resolves(mockCertificate)
      existsSyncStub.returns(false)
      
      await execute({
        kubeConfigPath: '~/.kube/custom-kube-config',
        kubernetesCluster: 'mockKubernetesConnectionId',
        jobToken: 'mockFlowJobToken'
      } as IParams)

      sinon.assert.calledWith(writeFileSyncStub, '/root/.kube/custom-kube-config', `apiVersion: v1
kind: Config
clusters:
- cluster:
    server: https://rdc.aliyuncs.com/mirana
  name: my-cluster
contexts:
- context:
    cluster: my-cluster
    user: my-user
  name: my-context
current-context: my-context
users:
- name: my-user
  user:
    token: somejwttoken`)
    })
})
